package com.ssy.lingxi.member.merchant.serviceimpl.base;

import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.member.MemberLevelTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberStatusEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.constant.*;
import com.ssy.lingxi.member.merchant.api.model.constant.MemberRightSpendTypeEnum;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.constant.MemberChannelTypeEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberInnerStatusEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberOuterStatusEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberStringEnum;
import com.ssy.lingxi.member.merchant.model.dto.ComplainSummaryDTO;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.LineChartItem;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.SubMemberDetailVO;
import com.ssy.lingxi.member.merchant.model.vo.maintenance.response.*;
import com.ssy.lingxi.member.merchant.model.vo.validate.response.MemberValidateDetailLevelVO;
import com.ssy.lingxi.member.merchant.repository.*;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberDetailService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberLevelConfigService;
import com.ssy.lingxi.member.merchant.utils.AgentAreaUtil;
import com.ssy.lingxi.member.merchant.utils.NumberUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * (内部)会员详细信息查询服务实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2020-09-07
 */
@Service
public class BaseMemberDetailServiceImpl implements IBaseMemberDetailService {
    @Resource
    private MemberRightHistoryRepository memberRightHistoryRepository;

    @Resource
    private MemberRightSpendHistoryRepository memberRightSpendHistoryRepository;

    @Resource
    private BaseCreditConfigRepository baseCreditConfigRepository;

    @Resource
    private MemberLevelConfigRepository memberLevelConfigRepository;

    @Resource
    private MemberLevelHistoryRepository memberLevelHistoryRepository;

    @Resource
    private MemberCreditRepository memberCreditRepository;

    @Resource
    private MemberTradeCommentHistoryRepository memberTradeCommentHistoryRepository;

    @Resource
    private MemberAfterSaleHistoryRepository memberAfterSaleHistoryRepository;

    @Resource
    private MemberComplainHistoryRepository memberComplainHistoryRepository;

    @Resource
    private MemberOrganizationRepository memberOrganizationRepository;

    @Resource
    private IBaseMemberLevelConfigService baseMemberLevelConfigService;

    @Resource
    private JdbcTemplate jdbcTemplate;

    /**
     * 查询下级会员详细信息
     *
     * @param relationDO 会员关系
     * @return 查询结果
     */
    @Override
    public SubMemberDetailVO getSubMemberDetail(MemberRelationDO relationDO) {
        SubMemberDetailVO detailVO = new SubMemberDetailVO();
        detailVO.setValidateId(relationDO.getId());
        detailVO.setMemberId(relationDO.getSubMemberId());
        detailVO.setName(relationDO.getSubMember().getName());
        detailVO.setStatus(relationDO.getStatus());
        detailVO.setStatusName(MemberStatusEnum.getCodeMessage(relationDO.getStatus()));
        detailVO.setInnerStatus(relationDO.getInnerStatus());
        detailVO.setInnerStatusName(MemberInnerStatusEnum.getCodeMsg(relationDO.getInnerStatus()));
        detailVO.setOuterStatus(relationDO.getOuterStatus());
        detailVO.setOuterStatusName(MemberOuterStatusEnum.getCodeMsg(relationDO.getOuterStatus()));
        detailVO.setMemberTypeEnum(relationDO.getSubMemberTypeEnum());
        detailVO.setMemberTypeName(MemberTypeEnum.getCodeMessage(relationDO.getSubMemberTypeEnum()));
        detailVO.setRoleName(relationDO.getSubRoleName());
        detailVO.setLevel(relationDO.getLevelRight() == null ? 0 : relationDO.getLevelRight().getLevel());
        detailVO.setLevelTag(relationDO.getLevelRight() == null ? "" : relationDO.getLevelRight().getLevelTag());
        detailVO.setAccount(relationDO.getSubMember().getAccount());
        detailVO.setPhone(relationDO.getSubMember().getPhone());
        detailVO.setEmail(relationDO.getSubMember().getEmail());
        detailVO.setRegisterTime(relationDO.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));

        //渠道信息
        if(relationDO.getSubMemberLevelTypeEnum().equals(MemberLevelTypeEnum.CHANNEL.getCode())) {
            detailVO.setChannelLevelTag(relationDO.getChannel().getChannelLevelTag());
            detailVO.setChannelTypeName(MemberChannelTypeEnum.getMsg(relationDO.getChannel().getChannelType().getChannelTypeEnum()));
            detailVO.setAreas(AgentAreaUtil.transferToList(relationDO.getChannel().getAgentArea()));
            detailVO.setRemark(relationDO.getChannel().getRemark());
        }

        return detailVO;
    }

    /**
     * 查询会员详情 - 会员等级信息
     *
     * @param relationDO 会员上下级关系
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberValidateDetailLevelVO> getMemberDetailLevel(MemberRelationDO relationDO) {
        MemberValidateDetailLevelVO levelVO = new MemberValidateDetailLevelVO();
        MemberLevelRightDO levelDO = relationDO.getLevelRight();
//        if (levelDO == null) {
//            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_DOES_NOT_EXIST);
//        }

        if (levelDO == null) {
            return Wrapper.success(levelVO);
        }

        levelVO.setLevelTag(levelDO.getLevelTag());
        levelVO.setScore(levelDO.getScore());
        levelVO.setNextScore(levelDO.getLevelConfig() == null ? 0 : levelDO.getLevelConfig().getPoint());
        levelVO.setNextLevelTag(baseMemberLevelConfigService.findNextLevelTag(relationDO, levelDO));

        //今年第一天
        LocalDateTime firstDay = LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear()).withHour(0).withMinute(0).withSecond(0);

        List<MemberLevelHistoryDO> historyDOList = memberLevelHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId());

        //汇总统计
        List<LineChartItem> itemList = historyDOList.stream().filter(h -> h.getCreateTime().isAfter(firstDay)).map(h -> {
            LineChartItem item = new LineChartItem();
            item.setX(h.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM")));
            item.setY(h.getScore());
            return item;
        }).collect(Collectors.groupingBy(LineChartItem::getX)).entrySet().stream().map(entry -> {
            LineChartItem item = new LineChartItem();
            item.setX(entry.getKey());
            item.setY(entry.getValue().stream().mapToInt(LineChartItem::getY).sum());
            return item;
        }).collect(Collectors.toList());

        levelVO.setPoints(itemList);

        return Wrapper.success(levelVO);
    }

    /**
     * 会员详情 - 分页查询会员等级历史记录
     *
     * @param relationDO 会员上下级关系
     * @param current    当前分页
     * @param pageSize   每页行数
     * @param formatter 日期时间格式
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailLevelHistoryVO>> pageMemberLevelDetailHistory(MemberRelationDO relationDO, int current, int pageSize, DateTimeFormatter formatter) {
        MemberLevelRightDO levelDO = relationDO.getLevelRight();
//        if (levelDO == null) {
//            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_DOES_NOT_EXIST);
//        }

        if (levelDO == null) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());
        Page<MemberLevelHistoryDO> result = memberLevelHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId(), page);
        List<MemberDetailLevelHistoryVO> historyVOList = result.getContent().stream().map(h -> {
            MemberDetailLevelHistoryVO historyVO = new MemberDetailLevelHistoryVO();
            historyVO.setId(h.getId());
            historyVO.setCreateTime(h.getCreateTime().format(formatter));
            historyVO.setRuleName(MemberLevelRuleTypeEnum.getCodeMsg(h.getLevelRuleTypeEnum()));
            historyVO.setScore(h.getScore());

            String remark;
            if(h.getLevelRuleTypeEnum().equals(MemberLevelRuleTypeEnum.BY_LOGIN.getCode())) {
                remark = MemberLevelRuleTypeEnum.BY_LOGIN.getMessage();
            } else {
                remark = StringUtils.hasLength(h.getRemark()) ? MemberStringEnum.ORDER_NO.getName().concat(":").concat(h.getRemark()) : "";
            }
            historyVO.setRemark(remark);

            return historyVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), historyVOList));
    }

    /**
     * 会员详情 - 会员权益信息
     *
     * @param relationDO 会员上下级关系
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailRightVO> getMemberDetailRight(MemberRelationDO relationDO) {
        MemberDetailRightVO rightVO = new MemberDetailRightVO();
        rightVO.setLevelTag("");
        rightVO.setSumReturnMoney(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        rightVO.setSumPoint(0);
        rightVO.setCurrentPoint(0);
        rightVO.setSumUsedPoint(0);
        rightVO.setRights(new ArrayList<>());

        MemberLevelRightDO levelRight = relationDO.getLevelRight();
        if (levelRight == null) {
            return Wrapper.success(rightVO);
        }

        rightVO.setLevelTag(levelRight.getLevelTag());
        rightVO.setCurrentPoint(levelRight.getCurrentPoint());
        rightVO.setSumPoint(levelRight.getSumPoint());
        //返现金额保留两位小数
        rightVO.setSumReturnMoney(levelRight.getSumReturnMoney().setScale(2, RoundingMode.HALF_UP));
        rightVO.setSumUsedPoint(levelRight.getSumUsedPoint());

        if(levelRight.getLevelConfig() == null || CollectionUtils.isEmpty(levelRight.getLevelConfig().getRights())) {
            return Wrapper.success(rightVO);
        }

        List<MemberDetailRightConfigVO> configVOList = levelRight.getLevelConfig().getRights().stream().map(memberRightConfigDO -> {
            MemberDetailRightConfigVO configVO = new MemberDetailRightConfigVO();
            configVO.setId(memberRightConfigDO.getId());
            configVO.setRightTypeEnum(memberRightConfigDO.getRightType());
            configVO.setName(MemberRightTypeEnum.getCodeMsg(memberRightConfigDO.getRightType()));
            configVO.setRemark(MemberRightTypeEnum.getRemark(memberRightConfigDO.getRightType()));
            configVO.setAcquireWay(MemberRightAcquireWayEnum.getCodeMsg(memberRightConfigDO.getAcquireWay()));
            configVO.setParamWay(MemberRightParamWayEnum.getCodeMsg(memberRightConfigDO.getParamWay()));
            configVO.setStatus(memberRightConfigDO.getStatus());
            BigDecimal parameter = BigDecimal.ZERO;
            if(memberRightConfigDO.getStatus().equals(EnableDisableStatus.DISABLE.getCode()) || NumberUtil.isNullOrZero(memberRightConfigDO.getParameter())) {
                if(memberRightConfigDO.getRightType().equals(MemberRightTypeEnum.PRICE_RIGHT.getCode())) {
                    parameter = BigDecimal.ONE;
                }
            } else {
                parameter = memberRightConfigDO.getParameter();
            }

            String param = parameter.multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString();
            configVO.setParameter(param);
            return configVO;
        }).collect(Collectors.toList());

        rightVO.setRights(configVOList);

        return Wrapper.success(rightVO);
    }

    /**
     * 会员详情 - 分页查询会员权益获取记录
     *
     * @param relationDO 会员上下级关系
     * @param current    当前分页
     * @param pageSize   每页行数
     * @param formatter 时间日期格式
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailRightHistoryVO>> pageMemberDetailRightHistory(MemberRelationDO relationDO, int current, int pageSize, DateTimeFormatter formatter) {
        MemberLevelRightDO levelDO = relationDO.getLevelRight();
//        if (levelDO == null) {
//            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_DOES_NOT_EXIST);
//        }

        if (levelDO == null) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());
        Page<MemberRightHistoryDO> result = memberRightHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId(), page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(r -> {
            MemberDetailRightHistoryVO historyVO = new MemberDetailRightHistoryVO();
            historyVO.setId(r.getId());
            historyVO.setCreateTime(r.getCreateTime().format(formatter));
            historyVO.setRightTypeName(MemberRightTypeEnum.getCodeMsg(r.getRightTypeEnum()));
            //保留两位小数，小数部分是0的话保留整数，小数第一位不是0的话则保留一位
            historyVO.setPoint(ServiceConfig.BIG_DECIMAL_FORMAT.format(r.getPoint()));
            historyVO.setRemark(r.getRemark());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员详情 - 分页查询会员权益使用记录
     *
     * @param relationDO 会员上下级关系
     * @param current    当前分页
     * @param pageSize   每页行数
     * @param formatter 日期时间格式
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailRightSpendHistoryVO>> pageMemberDetailRightSpendHistory(MemberRelationDO relationDO, int current, int pageSize, DateTimeFormatter formatter) {
        MemberLevelRightDO levelDO = relationDO.getLevelRight();
//        if (levelDO == null) {
//            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_LEVEL_DOES_NOT_EXIST);
//        }

        if (levelDO == null) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());
        Page<MemberRightSpendHistoryDO> result = memberRightSpendHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId(), page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(r -> {
            MemberDetailRightSpendHistoryVO historyVO = new MemberDetailRightSpendHistoryVO();
            historyVO.setId(r.getId());
            historyVO.setCreateTime(r.getCreateTime().format(formatter));
            historyVO.setRightTypeName(MemberRightTypeEnum.getCodeMsg(r.getRightTypeEnum()));
            historyVO.setSpendTypeName(MemberRightSpendTypeEnum.getNameByCode(r.getSpendTypeEnum()));
            historyVO.setPoint(r.getPoint());
            historyVO.setRemark(r.getRemark());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员详情 - 会员信用信息
     *
     * @param relationDO 会员上下级关系
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditVO> getMemberDetailCredit(MemberRelationDO relationDO) {
        MemberCreditDO creditDO = relationDO.getCredit();
        if (creditDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_CREDIT_DOES_NOT_EXIST);
        }

        MemberDetailCreditVO creditVO = new MemberDetailCreditVO();
        creditVO.setAfterSaleCommentPoint(creditDO.getAfterSaleCommentPoint());
        creditVO.setComplainPoint(creditDO.getComplainPoint());
        creditVO.setCreditPoint(creditDO.getCreditPoint());
        creditVO.setRegisterYearsPoint(creditDO.getRegisterYearsPoint());
        creditVO.setTradeCommentPoint(creditDO.getTradeCommentPoint());

        List<BaseCreditConfigDO> configDOList = baseCreditConfigRepository.findByStatus(EnableDisableStatus.ENABLE.getCode());
        creditVO.setConfigs(configDOList.stream().map(c -> {
            MemberDetailCreditVO.CreditConfigItem item = new MemberDetailCreditVO.CreditConfigItem();
            item.setId(c.getId());
            item.setCreditTypeEnum(c.getCreditTypeEnum());
            item.setCreditTypeName(MemberCreditTypeEnum.getNameByCode(c.getCreditTypeEnum()));
            item.setCreditPoint(c.getCreditPoint());
            item.setRemark(MemberCreditTypeEnum.getRemark(c.getCreditTypeEnum()));
            if(c.getCreditTypeEnum().equals(MemberCreditTypeEnum.BY_TRADE_COMMENT_FIVE_STARS.getCode())) {
                item.setCurrentPoint(creditDO.getTradeCommentPoint());
            } else if(c.getCreditTypeEnum().equals(MemberCreditTypeEnum.BY_COMPLAIN.getCode())) {
                item.setCurrentPoint(creditDO.getComplainPoint());
            } else if(c.getCreditTypeEnum().equals(MemberCreditTypeEnum.BY_COMMENT_AFTER_TRADE.getCode())) {
                item.setCurrentPoint(creditDO.getAfterSaleCommentPoint());
            } else if(c.getCreditTypeEnum().equals(MemberCreditTypeEnum.BY_REGISTER_YEARS.getCode())) {
                item.setCurrentPoint(creditDO.getRegisterYearsPoint());
            } else {
                item.setCurrentPoint(0);
            }

            return item;
        }).collect(Collectors.toList()));

        return Wrapper.success(creditVO);
    }

    /**
     * 会员详情 - 会员信用信息(平台层面汇总)
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditVO> getAllMemberDetailCredit(Long subMemberId, Long subRoleId) {
        List<MemberCreditDO> creditDOList = memberCreditRepository.findBySubMemberIdAndSubRoleId(subMemberId, subRoleId);
        Integer sumAfterSaleCommentPoint = creditDOList.stream().map(MemberCreditDO::getAfterSaleCommentPoint).reduce(Integer::sum).orElse(0);
        Integer sumComplainPoint = creditDOList.stream().map(MemberCreditDO::getComplainPoint).reduce(Integer::sum).orElse(0);
        Integer sumCreditPoint = creditDOList.stream().map(MemberCreditDO::getCreditPoint).reduce(Integer::sum).orElse(0);
        Integer sumRegisterYearsPoint = creditDOList.stream().map(MemberCreditDO::getRegisterYearsPoint).reduce(Integer::sum).orElse(0);
        Integer sumTradeCommentPoint = creditDOList.stream().map(MemberCreditDO::getTradeCommentPoint).reduce(Integer::sum).orElse(0);

        MemberDetailCreditVO creditVO = new MemberDetailCreditVO();
        creditVO.setAfterSaleCommentPoint(sumAfterSaleCommentPoint);
        creditVO.setComplainPoint(sumComplainPoint);
        creditVO.setCreditPoint(sumCreditPoint);
        creditVO.setRegisterYearsPoint(sumRegisterYearsPoint);
        creditVO.setTradeCommentPoint(sumTradeCommentPoint);

        List<BaseCreditConfigDO> configDOList = baseCreditConfigRepository.findByStatus(EnableDisableStatus.ENABLE.getCode());
        creditVO.setConfigs(configDOList.stream().map(c -> {
            MemberDetailCreditVO.CreditConfigItem item = new MemberDetailCreditVO.CreditConfigItem();
            item.setId(c.getId());
            item.setCreditTypeName(MemberCreditTypeEnum.getNameByCode(c.getCreditTypeEnum()));
            item.setCreditPoint(c.getCreditPoint());
            item.setRemark(MemberCreditTypeEnum.getRemark(c.getCreditTypeEnum()));
            if(c.getCreditTypeEnum().equals(MemberCreditTypeEnum.BY_TRADE_COMMENT_FIVE_STARS.getCode())) {
                item.setCurrentPoint(sumTradeCommentPoint);
            } else if(c.getCreditTypeEnum().equals(MemberCreditTypeEnum.BY_COMPLAIN.getCode())) {
                item.setCurrentPoint(sumComplainPoint);
            } else if(c.getCreditTypeEnum().equals(MemberCreditTypeEnum.BY_COMMENT_AFTER_TRADE.getCode())) {
                item.setCurrentPoint(sumAfterSaleCommentPoint);
            } else if(c.getCreditTypeEnum().equals(MemberCreditTypeEnum.BY_REGISTER_YEARS.getCode())) {
                item.setCurrentPoint(sumRegisterYearsPoint);
            } else {
                item.setCurrentPoint(0);
            }
            return item;
        }).collect(Collectors.toList()));

        return Wrapper.success(creditVO);
    }

    /**
     * 会员详情 - 会员信用 - 交易评价汇总
     *
     * @param relationDO 会员上下级关系
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditCommentSummaryVO> getMemberDetailCreditTradeCommentSummary(MemberRelationDO relationDO) {
        MemberDetailCreditCommentSummaryVO summaryVO = new MemberDetailCreditCommentSummaryVO();
        List<MemberTradeCommentHistoryDO> historyDOList = memberTradeCommentHistoryRepository.findAllByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId());

        //四舍五入计算平均星级
        double avgStarD = historyDOList.stream().mapToInt(MemberTradeCommentHistoryDO::getStar).average().orElse(0);
        Integer avgStar = Double.valueOf(Math.round(avgStarD)).intValue();
        summaryVO.setAvgStar(avgStar);

        //循环计算
        LocalDateTime last7days = LocalDateTime.now().minusDays(7);
        LocalDateTime last30days = LocalDateTime.now().minusDays(30);
        LocalDateTime last180days = LocalDateTime.now().minusDays(180);

        List<MemberDetailCreditCommentSummaryVO.TableRow> rows = Stream.of(5, 4, 3, 2, 1).map(star -> {
            MemberDetailCreditCommentSummaryVO.TableRow tableRow = new MemberDetailCreditCommentSummaryVO.TableRow();
            List<MemberTradeCommentHistoryDO> subList = historyDOList.stream().filter(h -> h.getStar().equals(star)).collect(Collectors.toList());

            long countIn7Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last7days)).count();
            long countIn30Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last30days)).count();
            long countIn180Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last180days)).count();
            long countBefore180Days = subList.stream().filter(h -> h.getCreateTime().isBefore(last180days)).count();
            long sum = countIn180Days + countBefore180Days;

            tableRow.setStar(star);
            tableRow.setLast7days(countIn7Days);
            tableRow.setLast30days(countIn30Days);
            tableRow.setLast180days(countIn180Days);
            tableRow.setBefore180days(countBefore180Days);
            tableRow.setSum(sum);
            return tableRow;
        }).collect(Collectors.toList());

        summaryVO.setRows(rows);

        return Wrapper.success(summaryVO);
    }


    /**
     * 会员详情 - 会员信用 - 交易评价汇总（平台层面汇总）
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditCommentSummaryVO> getAllMemberDetailCreditTradeCommentSummary(Long subMemberId, Long subRoleId) {
        MemberDetailCreditCommentSummaryVO summaryVO = new MemberDetailCreditCommentSummaryVO();
        List<MemberTradeCommentHistoryDO> historyDOList = memberTradeCommentHistoryRepository.findAllBySubMemberIdAndSubRoleId(subMemberId, subRoleId);

        //四舍五入计算平均星级
        double avgStarD = historyDOList.stream().mapToInt(MemberTradeCommentHistoryDO::getStar).average().orElse(0);
        Integer avgStar = Double.valueOf(Math.round(avgStarD)).intValue();
        summaryVO.setAvgStar(avgStar);

        //循环计算
        LocalDateTime last7days = LocalDateTime.now().minusDays(7);
        LocalDateTime last30days = LocalDateTime.now().minusDays(30);
        LocalDateTime last180days = LocalDateTime.now().minusDays(180);

        List<MemberDetailCreditCommentSummaryVO.TableRow> rows = Stream.of(5, 4, 3, 2, 1).map(star -> {
            MemberDetailCreditCommentSummaryVO.TableRow tableRow = new MemberDetailCreditCommentSummaryVO.TableRow();
            List<MemberTradeCommentHistoryDO> subList = historyDOList.stream().filter(h -> h.getStar().equals(star)).collect(Collectors.toList());

            long countIn7Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last7days)).count();
            long countIn30Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last30days)).count();
            long countIn180Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last180days)).count();
            long countBefore180Days = subList.stream().filter(h -> h.getCreateTime().isBefore(last180days)).count();
            long sum = countIn180Days + countBefore180Days;

            tableRow.setStar(star);
            tableRow.setLast7days(countIn7Days);
            tableRow.setLast30days(countIn30Days);
            tableRow.setLast180days(countIn180Days);
            tableRow.setBefore180days(countBefore180Days);
            tableRow.setSum(sum);
            return tableRow;
        }).collect(Collectors.toList());

        summaryVO.setRows(rows);

        return Wrapper.success(summaryVO);
    }

    /**
     * 会员详情 - 会员信用 - 分页查询交易评论历史记录
     *
     * @param relationDO 会员上下级关系
     * @param starLevel 评论级别
     * @param current    当前分页
     * @param pageSize   每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailCreditTradeHistoryVO>> pageMemberDetailCreditTradeCommentHistory(MemberRelationDO relationDO, Integer starLevel, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());

        final Integer oneOrTwoStarsLevel = 1;
        final Integer threeStarsLevel = 2;
        final Integer fourOrFiveStarsLevel = 3;

        Specification<MemberTradeCommentHistoryDO> specification = (Specification<MemberTradeCommentHistoryDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //上级会员id和角色Id
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), relationDO.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), relationDO.getRoleId()));
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), relationDO.getSubMemberId()));
            list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), relationDO.getSubRoleId()));

            if (starLevel != null) {
                if (starLevel.equals(oneOrTwoStarsLevel)) {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 1), criteriaBuilder.equal(root.get("star").as(Integer.class), 2)));
                } else if (starLevel.equals(threeStarsLevel)) {
                    list.add(criteriaBuilder.equal(root.get("star").as(Integer.class), 3));
                } else {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 4), criteriaBuilder.equal(root.get("star").as(Integer.class), 5)));
                }
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberTradeCommentHistoryDO> result = memberTradeCommentHistoryRepository.findAll(specification, page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(h -> {
            MemberDetailCreditTradeHistoryVO historyVO = new MemberDetailCreditTradeHistoryVO();
            historyVO.setId(h.getId());
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setDealTime(h.getDealTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setStar(h.getStar());
            historyVO.setByMemberName(h.getMemberName());
            historyVO.setComment(h.getComment());
            historyVO.setProduct(h.getProduct());
            historyVO.setOrderNo(h.getOrderNo());
            historyVO.setPrice(h.getPrice());
            historyVO.setPurchaseCount(h.getDealCount());
            historyVO.setOrderId(h.getOrderId());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员详情 - 会员信用 - 分页查询交易评论历史记录（平台层面汇总）
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @param starLevel   评论等级
     * @param current     当前分页
     * @param pageSize    每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailCreditTradeHistoryVO>> pageAllMemberDetailCreditTradeCommentHistory(Long subMemberId, Long subRoleId, Integer starLevel, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());

        final Integer oneOrTwoStarsLevel = 1;
        final Integer threeStarsLevel = 2;

        Specification<MemberTradeCommentHistoryDO> specification = (Specification<MemberTradeCommentHistoryDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //下级会员id和角色Id
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), subMemberId));
            list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), subRoleId));

            if (starLevel != null) {
                if (starLevel.equals(oneOrTwoStarsLevel)) {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 1), criteriaBuilder.equal(root.get("star").as(Integer.class), 2)));
                } else if (starLevel.equals(threeStarsLevel)) {
                    list.add(criteriaBuilder.equal(root.get("star").as(Integer.class), 3));
                } else {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 4), criteriaBuilder.equal(root.get("star").as(Integer.class), 5)));
                }
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberTradeCommentHistoryDO> result = memberTradeCommentHistoryRepository.findAll(specification, page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(h -> {
            MemberDetailCreditTradeHistoryVO historyVO = new MemberDetailCreditTradeHistoryVO();
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setDealTime(h.getDealTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setStar(h.getStar());
            historyVO.setByMemberName(h.getMemberName());
            historyVO.setComment(h.getComment());
            historyVO.setProduct(h.getProduct());
            historyVO.setOrderNo(h.getOrderNo());
            historyVO.setPrice(h.getPrice());
            historyVO.setPurchaseCount(h.getDealCount());
            historyVO.setOrderId(h.getOrderId());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员详情 - 会员信用 - 售后评价汇总
     *
     * @param relationDO 会员上下级关系
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditCommentSummaryVO> getMemberDetailCreditAfterSaleCommentSummary(MemberRelationDO relationDO) {
        MemberDetailCreditCommentSummaryVO summaryVO = new MemberDetailCreditCommentSummaryVO();

        List<MemberAfterSaleHistoryDO> historyDOList = memberAfterSaleHistoryRepository.findAllByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId());

        //四舍五入计算平均星级
        double avgStarD = historyDOList.stream().mapToInt(MemberAfterSaleHistoryDO::getStar).average().orElse(0);
        Integer avgStar = Double.valueOf(Math.round(avgStarD)).intValue();
        summaryVO.setAvgStar(avgStar);

        //循环计算
        LocalDateTime last7days = LocalDateTime.now().minusDays(7);
        LocalDateTime last30days = LocalDateTime.now().minusDays(30);
        LocalDateTime last180days = LocalDateTime.now().minusDays(180);

        List<MemberDetailCreditCommentSummaryVO.TableRow> rows = Stream.of(5, 4, 3, 2, 1).map(star -> {
            MemberDetailCreditCommentSummaryVO.TableRow tableRow = new MemberDetailCreditCommentSummaryVO.TableRow();
            List<MemberAfterSaleHistoryDO> subList = historyDOList.stream().filter(h -> h.getStar().equals(star)).collect(Collectors.toList());

            long countIn7Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last7days)).count();
            long countIn30Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last30days)).count();
            long countIn180Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last180days)).count();
            long countBefore180Days = subList.stream().filter(h -> h.getCreateTime().isBefore(last180days)).count();
            long sum = countIn180Days + countBefore180Days;

            tableRow.setStar(star);
            tableRow.setLast7days(countIn7Days);
            tableRow.setLast30days(countIn30Days);
            tableRow.setLast180days(countIn180Days);
            tableRow.setBefore180days(countBefore180Days);
            tableRow.setSum(sum);
            return tableRow;
        }).collect(Collectors.toList());

        summaryVO.setRows(rows);

        return Wrapper.success(summaryVO);
    }

    /**
     * 会员详情 - 会员信用 - 售后评价汇总（平台层面汇总）
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditCommentSummaryVO> getAllMemberDetailCreditAfterSaleCommentSummary(Long subMemberId, Long subRoleId) {
        MemberDetailCreditCommentSummaryVO summaryVO = new MemberDetailCreditCommentSummaryVO();

        List<MemberAfterSaleHistoryDO> historyDOList = memberAfterSaleHistoryRepository.findAllBySubMemberIdAndSubRoleId(subMemberId, subRoleId);

        //四舍五入计算平均星级
        double avgStarD = historyDOList.stream().mapToInt(MemberAfterSaleHistoryDO::getStar).average().orElse(0);
        Integer avgStar = Double.valueOf(Math.round(avgStarD)).intValue();
        summaryVO.setAvgStar(avgStar);

        //循环计算
        LocalDateTime last7days = LocalDateTime.now().minusDays(7);
        LocalDateTime last30days = LocalDateTime.now().minusDays(30);
        LocalDateTime last180days = LocalDateTime.now().minusDays(180);

        List<MemberDetailCreditCommentSummaryVO.TableRow> rows = Stream.of(5, 4, 3, 2, 1).map(star -> {
            MemberDetailCreditCommentSummaryVO.TableRow tableRow = new MemberDetailCreditCommentSummaryVO.TableRow();
            List<MemberAfterSaleHistoryDO> subList = historyDOList.stream().filter(h -> h.getStar().equals(star)).collect(Collectors.toList());

            long countIn7Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last7days)).count();
            long countIn30Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last30days)).count();
            long countIn180Days = subList.stream().filter(h -> h.getCreateTime().isAfter(last180days)).count();
            long countBefore180Days = subList.stream().filter(h -> h.getCreateTime().isBefore(last180days)).count();
            long sum = countIn180Days + countBefore180Days;

            tableRow.setStar(star);
            tableRow.setLast7days(countIn7Days);
            tableRow.setLast30days(countIn30Days);
            tableRow.setLast180days(countIn180Days);
            tableRow.setBefore180days(countBefore180Days);
            tableRow.setSum(sum);
            return tableRow;
        }).collect(Collectors.toList());

        summaryVO.setRows(rows);

        return Wrapper.success(summaryVO);
    }

    /**
     * 会员详情 - 会员信用 - 分页查询售后评论历史记录
     *
     * @param relationDO 会员上下级关系
     * @param starLevel  评论等级
     * @param current    当前分页
     * @param pageSize   每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailCreditAfterSaleHistoryVO>> pageMemberDetailCreditAfterSaleCommentHistory(MemberRelationDO relationDO, Integer starLevel, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());

        final Integer oneOrTwoStarsLevel = 1;
        final Integer threeStarsLevel = 2;

        Specification<MemberAfterSaleHistoryDO> specification = (Specification<MemberAfterSaleHistoryDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //上级会员id和角色Id
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), relationDO.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), relationDO.getRoleId()));
            //下级会员id和角色Id
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), relationDO.getSubMemberId()));
            list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), relationDO.getSubRoleId()));

            if (starLevel != null) {
                if (starLevel.equals(oneOrTwoStarsLevel)) {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 1), criteriaBuilder.equal(root.get("star").as(Integer.class), 2)));
                } else if (starLevel.equals(threeStarsLevel)) {
                    list.add(criteriaBuilder.equal(root.get("star").as(Integer.class), 3));
                } else {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 4), criteriaBuilder.equal(root.get("star").as(Integer.class), 5)));
                }
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberAfterSaleHistoryDO> result = memberAfterSaleHistoryRepository.findAll(specification, page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(h -> {
            MemberDetailCreditAfterSaleHistoryVO historyVO = new MemberDetailCreditAfterSaleHistoryVO();
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setStar(h.getStar());
            historyVO.setByMemberName(h.getMemberName());
            historyVO.setComment(h.getComment());
            historyVO.setProduct(h.getProduct());
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员详情 - 会员信用 - 分页查询售后评论历史记录（平台层面汇总）
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @param starLevel   评论等级
     * @param current     当前分页
     * @param pageSize    每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailCreditAfterSaleHistoryVO>> pageAllMemberDetailCreditAfterSaleCommentHistory(Long subMemberId, Long subRoleId, Integer starLevel, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());

        final Integer oneOrTwoStarsLevel = 1;
        final Integer threeStarsLevel = 2;

        Specification<MemberAfterSaleHistoryDO> specification = (Specification<MemberAfterSaleHistoryDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //下级会员id和角色Id
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), subMemberId));
            list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), subRoleId));

            if (starLevel != null) {
                if (starLevel.equals(oneOrTwoStarsLevel)) {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 1), criteriaBuilder.equal(root.get("star").as(Integer.class), 2)));
                } else if (starLevel.equals(threeStarsLevel)) {
                    list.add(criteriaBuilder.equal(root.get("star").as(Integer.class), 3));
                } else {
                    list.add(criteriaBuilder.or(criteriaBuilder.equal(root.get("star").as(Integer.class), 4), criteriaBuilder.equal(root.get("star").as(Integer.class), 5)));
                }
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberAfterSaleHistoryDO> result = memberAfterSaleHistoryRepository.findAll(specification, page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(h -> {
            MemberDetailCreditAfterSaleHistoryVO historyVO = new MemberDetailCreditAfterSaleHistoryVO();
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setStar(h.getStar());
            historyVO.setByMemberName(h.getMemberName());
            historyVO.setComment(h.getComment());
            historyVO.setProduct(h.getProduct());
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员详情 - 会员信用 - 投诉汇总
     *
     * @param relationDO 会员上下级关系
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditComplainSummaryVO> getMemberDetailCreditComplainSummary(MemberRelationDO relationDO) {
        MemberDetailCreditComplainSummaryVO summaryVO = new MemberDetailCreditComplainSummaryVO();

        String countSqlStr = "select count(*) as total, sum(case when date_part('day',  localtimestamp - create_time) <=7 then 1 else 0 end) as in7days, sum(case when date_part('day',  localtimestamp - create_time) <=30 then 1 else 0 end) as in30days, sum(case when date_part('day',  localtimestamp - create_time) <=180 then 1 else 0 end) as in180days, sum(case when date_part('day',  localtimestamp - create_time) >180 then 1 else 0 end) as before180days from ms_mc_member_complain_history ";
        String whereSqlStr = String.format("where member_id  = %d and role_id = %d and sub_member_id = %d and sub_role_id = %d ", relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId());
        String groupSqlStr = "group by member_id, role_id, sub_member_id, sub_role_id";

        String sql = countSqlStr.concat(whereSqlStr).concat(groupSqlStr);

        ComplainSummaryDTO summaryDTO = new ComplainSummaryDTO(0,0,0,0,0);
        List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
        if(!CollectionUtils.isEmpty(result)) {
            Map<String, Object> map = result.get(0);
            summaryDTO.setTotal((long) map.get("total"));
            summaryDTO.setIn7days((long) map.get("in7days"));
            summaryDTO.setIn30days((long) map.get("in30days"));
            summaryDTO.setIn180days((long) map.get("in180days"));
            summaryDTO.setBefore180days((long) map.get("before180days"));
        }

        return Wrapper.success(summaryVO);
    }

    /**
     * 会员详情 - 会员信用 - 投诉汇总（平台层面汇总）
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberDetailCreditComplainSummaryVO> getAllMemberDetailCreditComplainSummary(Long subMemberId, Long subRoleId) {
        MemberDetailCreditComplainSummaryVO summaryVO = new MemberDetailCreditComplainSummaryVO();

        List<MemberComplainHistoryDO> historyDOList = memberComplainHistoryRepository.findAllBySubMemberIdAndSubRoleId(subMemberId, subRoleId);

        //计算
        LocalDateTime last7days = LocalDateTime.now().minusDays(7);
        LocalDateTime last30days = LocalDateTime.now().minusDays(30);
        LocalDateTime last180days = LocalDateTime.now().minusDays(180);

        long countIn7Days = historyDOList.stream().filter(h -> h.getCreateTime().isAfter(last7days)).count();
        long countIn30Days = historyDOList.stream().filter(h -> h.getCreateTime().isAfter(last30days)).count();
        long countIn180Days = historyDOList.stream().filter(h -> h.getCreateTime().isAfter(last180days)).count();
        long countBefore180Days = historyDOList.stream().filter(h -> h.getCreateTime().isBefore(last180days)).count();
        long sum = countIn180Days + countBefore180Days;

        summaryVO.setLast7days(countIn7Days);
        summaryVO.setLast30days(countIn30Days);
        summaryVO.setLast180days(countIn180Days);
        summaryVO.setBefore180days(countBefore180Days);
        summaryVO.setSum(sum);

        return Wrapper.success(summaryVO);
    }

    /**
     * 会员详情 - 会员信用 - 分页查询投诉历史记录
     *
     * @param relationDO 会员上下级关系
     * @param current    当前分页
     * @param pageSize   每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailCreditComplainHistoryVO>> pageMemberDetailCreditComplainHistory(MemberRelationDO relationDO, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());
        Page<MemberComplainHistoryDO> result = memberComplainHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId(), page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(h -> {
            MemberDetailCreditComplainHistoryVO historyVO = new MemberDetailCreditComplainHistoryVO();
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setContent(h.getContent());
            historyVO.setByMemberName(h.getMemberName());
            historyVO.setReason(h.getReason());
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员详情 - 会员信用 - 分页查询投诉历史记录(平台层面汇总)
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @param current     当前分页
     * @param pageSize    每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberDetailCreditComplainHistoryVO>> pageAllMemberDetailCreditComplainHistory(Long subMemberId, Long subRoleId, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());
        Page<MemberComplainHistoryDO> result = memberComplainHistoryRepository.findAllBySubMemberIdAndSubRoleId(subMemberId, subRoleId, page);

        return Wrapper.success(new PageData<>(result.getTotalElements(), result.getContent().stream().map(h -> {
            MemberDetailCreditComplainHistoryVO historyVO = new MemberDetailCreditComplainHistoryVO();
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setContent(h.getContent());
            historyVO.setByMemberName(h.getMemberName());
            historyVO.setReason(h.getReason());
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 分页查询会员组织机构
     *
     * @param memberId 会员Id
     * @param current  当前分页
     * @param pageSize 每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberOrganizationQueryVO>> pageMemberOrganizations(Long memberId, String code, String title, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current -1, pageSize, Sort.by("id").ascending());
        Specification<MemberOrganizationDO> specification = (Specification<MemberOrganizationDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("member").as(MemberDO.class), memberId));
            if(StringUtils.hasLength(code)) {
                list.add(criteriaBuilder.like(root.get("code").as(String.class), "%" + code.trim() + "%"));
            }

            if(StringUtils.hasLength(title)) {
                list.add(criteriaBuilder.like(root.get("title").as(String.class), "%" + title.trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberOrganizationDO> pageList = memberOrganizationRepository.findAll(specification, pageable);
        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(org -> {
            MemberOrganizationQueryVO queryVO = new MemberOrganizationQueryVO();
            queryVO.setId(org.getId());
            queryVO.setTitle(org.getTitle());
            queryVO.setCode(org.getCode());
            queryVO.setRemark(StringUtils.hasLength(org.getRemark()) ? org.getRemark() : "");
            return queryVO;
        }).collect(Collectors.toList())));
    }
}
